﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BookingDB.Models;
using GenericModels;

namespace CTRLayer
{

    public class CTRBooking
    {
        private CTRPerson personCtr;
        private CTRShow showCtr;
        private BioBookingContext db;


        public CTRBooking()
        {
            personCtr = new CTRPerson();
            showCtr = new CTRShow();
            db = new BioBookingContext();
        }

        /// <summary>
        /// Create and return an empty instance of a booking
        /// </summary>
        /// <returns>A Booking</returns>
        public Booking CreateLocalBooking()
        {
            Booking booking = new Booking();

            return booking;
        }

        /// <summary>
        /// Create and return an empty instance of a partbooking
        /// </summary>
        /// <returns>A PartBooking</returns>
        public PartBooking CreateLocalPartBooking()
        {
            PartBooking part = new PartBooking();

            return part;
        }

        /// <summary>
        /// Finds a specific booking based on it´s id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Booking GetBookingById(int id)
        {
            EntityBooking eBooking = (from b in db.Bookings
                                      where b.id == id
                                      select b).SingleOrDefault();
            
            return TranslateBooking(eBooking);
        }

        /// <summary>
        /// Creates a booking entity and inserts it into the database,
        /// said booking entity is then converted into a generic booking object which is returned.
        /// </summary>
        /// <param name="empId"></param>
        /// <param name="totalPrice"></param>
        /// <param name="isCollected"></param>
        /// <returns>A Booking</returns>
        public Booking InsertBooking(Booking booking)
        {
            EntityBooking eBooking = new EntityBooking()
                                    {
                                        employee_Id = booking.EmpId,
                                        totalPrice = (decimal) booking.TotalPrice,
                                        isCollected = booking.IsCollected
                                    };
            db.Bookings.Add(eBooking);
            db.SaveChanges();
            return TranslateBooking(eBooking);
        }




        /// <summary>
        /// Create a partbooking entity and insert it into the database.
        /// Then convert same object to a generic model, and return the partbooking
        /// </summary>
        /// <param name="show"></param>
        /// <param name="booking"></param>
        /// <returns>A partbooking</returns>
        public PartBooking InsertPartBooking(PartBooking part)
        {
            EntityPartBooking ePart = new EntityPartBooking()
                                      {
                                          show_Id = part.TheShow.Show_Id,
                                          isPaid = false,
                                          booking_id = part.BookingId
                                      };
            db.PartBookings.Add(ePart);
            db.SaveChanges();

            return TranslatePartBooking(ePart);

        }

        /// <summary>
        /// Updates the totalprice of the collected booking, and whether the tickets has been collected
        /// </summary>
        /// <param name="booking"></param>
        /// <param name="part"></param>
        /// <param name="isCollected"></param>
        /// <returns>A Bool</returns>
        public bool UpdateBooking(Booking booking)
        {
            bool updated = false;



            EntityBooking eBooking = (from b in db.Bookings
                                      where b.id == booking.BookingId
                                      select b).Single();


            return updated;

        }

        /// <summary>
        /// Deletes a partbooking from a booking, based on their id´s
        /// </summary>
        /// <param name="booking"></param>
        /// <param name="part"></param>
        /// <returns>A bool</returns>
        public bool DeletePartBooking(Booking booking, PartBooking part)
        {
            bool deleted = false;

            try
            {
                EntityPartBooking ePart = (from ep in db.PartBookings
                                           where ep.booking_id == booking.BookingId && ep.id == part.Id
                                           select ep).Single();
                db.Set<EntityPartBooking>().Remove(ePart);
                db.SaveChanges();
                deleted = true;
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: " + e);
            }

            return deleted;

        }

        #region Translate Methods
        /// <summary>
        /// Helper method which translates the retrieved entity framework object into a generic model
        /// </summary>
        /// <param name="eBooking"></param>
        /// <returns>A Booking</returns>
        private Booking TranslateBooking(EntityBooking eBooking)
        {
            Booking b = new Booking();

            b.BookingId = eBooking.id;
            b.EmpId = (int)eBooking.employee_Id;
            b.TotalPrice = (float)eBooking.totalPrice;

            if(eBooking.customer_id != null)
            b.Customer_id = (int)eBooking.customer_id;

            foreach (EntityPartBooking epb in eBooking.PartBookings)
            {
                b.PbList.Add(TranslatePartBooking(epb));
            }

            return b;
        }

        /// <summary>
        /// Helper method which translates the retrieved entity framework object into a generic model
        /// Makes use of the showCtr to create the show.
        /// </summary>
        /// <param name="ePart"></param>
        /// <returns></returns>
        private PartBooking TranslatePartBooking(EntityPartBooking ePart)
        {
            PartBooking part = new PartBooking();

            part.Id = ePart.id;
            part.BookingId = (int)ePart.booking_id;
            part.IsPaid = (bool)ePart.isPaid;
            part.TheShow = showCtr.GetShow(ePart.show_Id.Value);    

            return part;
        }
        #endregion 


    }
    
}
